package com.spdg.ring.offline;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import cn.wolf.tools.Frequency;
import cn.wolf.tools.Log;
import cn.wolf.tools.StreamUtil;

/**
 * <p>Title: 离线包下载线程 </p>
 * <p>Description:  </p>
 * <p>@author: caijj                </p>
 * <p>Copyright: Copyright (c) 2012    </p>
 * <p>Company: HX Co., Ltd.          </p>
 * <p>Create Time: 2012-11-17             </p>
 * <p>Update Time:                     </p>
 * <p>Updater:                         </p>
 * <p>Update Comments:                 </p>
 */
public class ZipDownload extends AsyncTask<Void, Progress, List<Progress>> {

	private List<Progress> list;

	DownloadListener mListener;
	private volatile boolean running;

	private Progress mCurrentProgress;
	private int total;

	public ZipDownload(List<Progress> list) {
		this.list = list;
	}

	public void setDownloadListener(DownloadListener listener) {
		this.mListener = listener;
	}

	@Override
	protected List<Progress> doInBackground(Void... params) {
		running = true;
		if (list == null || list.isEmpty()) {
			running = false;
		}

		int size = list.size();
		int index = 0;
		while (running && index < size) {
			mCurrentProgress = list.get(index);
			mCurrentProgress.index = index;

			int trycount = 0;
			while (total <= 0) {
				init(mCurrentProgress);
				trycount++;

				if (trycount >= 3) { // 重试3次，退出
					running = false;
					error(new DownloadException("network error.."));
					break;
				}
			}

			if (!running) {
				break;
			}

			download(mCurrentProgress);
			index++;
		}
		return list;
	}

	private int init(Progress p) {

		String url = p.url;
		HttpURLConnection conn = null;
		total = 0;
		try {
			HttpClient httpClient = new DefaultHttpClient();
			// 3 秒超时
			httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);

			HttpGet get = new HttpGet(url);
			HttpResponse response = httpClient.execute(get);
			total = (int) response.getEntity().getContentLength();
			// URL u = new URL(url);
			// conn = ((HttpURLConnection) u.openConnection());
			// conn.setConnectTimeout(5000);
			// total = conn.getContentLength();
		} catch (MalformedURLException e) {
			// e.printStackTrace();
			Log.e(e.getMessage(), e);
		} catch (IOException e) {
			// e.printStackTrace();
			Log.e(e.getMessage(), e);
		} finally {
			if (conn != null) {
				conn.disconnect();
				conn = null;
			}
		}
		return total;
	}

	private void download(Progress p) {
		String fileName = p.fileName;
		String filePath = p.filePath;
		String url = p.url;
		boolean downloadSuccess = false;

		HttpURLConnection conn = null;
		RandomAccessFile rf = null;
		InputStream in = null;
		File file = null;
		FileOutputStream out = null;
		try {

			file = newFile(fileName, filePath);
			out = new FileOutputStream(file);

			Frequency fre = new Frequency(600);

			URL u = new URL(url);
			conn = ((HttpURLConnection) u.openConnection());
			conn.setConnectTimeout(5000);
			conn.setReadTimeout(7000);

			p.total = total;

			in = conn.getInputStream();
			byte[] buffer = new byte[102400];
			int len = 0;
			while ((len = in.read(buffer)) > 0 && running) {
				out.write(buffer, 0, len);
				p.complete += len;

				if (fre.toRun() || running) {// 限制频率
					publishProgress(p);
				}
			}

			postProgress(p);
			downloadSuccess = true;
			total = 0;

		} catch (MalformedURLException e) {
			// e.printStackTrace();
			error(new DownloadException(e.getMessage(), e));
			running = false;
		} catch (IOException e) {
			// e.printStackTrace();
			error(new DownloadException("network error..", e));
			running = false;

		} finally {
			// Closes this stream.
			StreamUtil.closeSilently(in);
			StreamUtil.closeSilently(out);
			StreamUtil.closeSilently(rf);

			if (!downloadSuccess) { // 下载失败，删除文件
				if (file != null && file.exists()) {
					file.delete();
				}
			}
			if (conn != null) {
				conn.disconnect();
			}
		}
	}

	private File newFile(String fileName, String fileDir) {
		File dir = new File(fileDir);

		if (!dir.exists()) {
			dir.mkdirs();
		}

		return new File(fileDir, fileName);
	}

	public void onManualProgress() {
		publishProgress(mCurrentProgress);
	}

	@Override
	protected void onProgressUpdate(Progress... values) {
		if (mListener != null) {
			mListener.onProgress(values[0]);
		}
	}

	// 异常
	private void error(DownloadException e) {
		sdHandler.obtainMessage(MESSAGE_POST_ERROR, new DownloadResult(this, null, e))
				.sendToTarget();
	}

	private void onError(DownloadException e) {
		if (mListener != null) {
			mListener.onError(e);
		}
	}

	private void postProgress(Progress progress) {
		sdHandler.obtainMessage(MESSAGE_POST_PROGRESS, new DownloadResult(this, progress, null))
				.sendToTarget();
	}

	protected void onPostProgress(Progress progress) {
		if (mListener != null) {
			mListener.onPostProgress(progress.index, progress);
		}
	}

	@Override
	protected void onPostExecute(List<Progress> result) {
		if (mListener != null) {
			mListener.onPostExecute(result);
		}
	}

	public void cancel() {
		cancel(true);
		running = false;
	}

	private static final int MESSAGE_POST_ERROR = 0x1;
	private static final int MESSAGE_POST_PROGRESS = 0x2;
	// private static final int MESSAGE_POST_PRE = 0x2;
	// private static final int MESSAGE_POST_TIME_OUT = 0x3;
	private static final InternalHandler sdHandler = new InternalHandler();

	private static class InternalHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			DownloadResult result = (DownloadResult) msg.obj;
			switch (msg.what) {
			case MESSAGE_POST_ERROR:
				result.loader.onError(result.error);
				break;
			case MESSAGE_POST_PROGRESS:
				result.loader.onPostProgress(result.progress);
				break;
			}
		}

	}

	private static class DownloadResult {

		final DownloadException error;
		final ZipDownload loader;
		final Progress progress;

		DownloadResult(ZipDownload loader, Progress progress, DownloadException e) {
			this.error = e;
			this.loader = loader;
			this.progress = progress;
		}
	}
}
